home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / VertexShader / VertexShader.cpp < prev    next >
C/C++ Source or Header  |  2001-10-31  |  17KB  |  498 lines

  1. //-----------------------------------------------------------------------------
  2. // File: VertexShader.cpp
  3. //
  4. // Desc: Example code showing how to do vertex shaders in D3D.
  5. //
  6. // Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #include <stdio.h>
  10. #include <math.h>
  11. #include <D3DX8.h>
  12. #include "D3DApp.h"
  13. #include "D3DFile.h"
  14. #include "D3DFont.h"
  15. #include "D3DUtil.h"
  16. #include "DXUtil.h"
  17. #include "resource.h"
  18.  
  19.  
  20.  
  21.  
  22. //-----------------------------------------------------------------------------
  23. // Name: class CMyD3DApplication
  24. // Desc: Application class. The base class (CD3DApplication) provides the 
  25. //       generic functionality needed in all Direct3D samples. CMyD3DApplication 
  26. //       adds functionality specific to this sample program.
  27. //-----------------------------------------------------------------------------
  28. class CMyD3DApplication : public CD3DApplication
  29. {
  30.     // Font for drawing text
  31.     CD3DFont* m_pFont;
  32.     CD3DFont* m_pFontSmall;
  33.  
  34.     // Scene
  35.     LPDIRECT3DVERTEXBUFFER8 m_pVB;
  36.     LPDIRECT3DINDEXBUFFER8  m_pIB;
  37.     DWORD        m_dwNumVertices;
  38.     DWORD        m_dwNumIndices;
  39.     DWORD        m_dwShader;
  40.     DWORD        m_dwSize;
  41.  
  42.     // Transforms
  43.     D3DXMATRIX  m_matPosition;
  44.     D3DXMATRIX  m_matView;
  45.     D3DXMATRIX  m_matProj;
  46.  
  47.     // Navigation
  48.     BYTE        m_bKey[256];
  49.     FLOAT       m_fSpeed;
  50.     FLOAT       m_fAngularSpeed;
  51.     BOOL        m_bShowHelp;
  52.  
  53.     D3DXVECTOR3 m_vVelocity;
  54.     D3DXVECTOR3 m_vAngularVelocity;
  55.  
  56. protected:
  57.     HRESULT OneTimeSceneInit();
  58.     HRESULT InitDeviceObjects();
  59.     HRESULT RestoreDeviceObjects();
  60.     HRESULT InvalidateDeviceObjects();
  61.     HRESULT DeleteDeviceObjects();
  62.     HRESULT FinalCleanup();
  63.     HRESULT Render();
  64.     HRESULT FrameMove();
  65.     HRESULT ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior, D3DFORMAT Format );
  66.     LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  67.  
  68. public:
  69.     CMyD3DApplication();
  70. };
  71.  
  72.  
  73.  
  74.  
  75. //-----------------------------------------------------------------------------
  76. // Name: WinMain()
  77. // Desc: Entry point to the program. Initializes everything, and goes into a
  78. //       message-processing loop. Idle time is used to render the scene.
  79. //-----------------------------------------------------------------------------
  80. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  81. {
  82.     CMyD3DApplication d3dApp;
  83.  
  84.     if( FAILED( d3dApp.Create( hInst ) ) )
  85.         return 0;
  86.  
  87.     return d3dApp.Run();
  88. }
  89.  
  90.  
  91.  
  92.  
  93. //-----------------------------------------------------------------------------
  94. // Name: CMyD3DApplication()
  95. // Desc: Application constructor. Sets attributes for the app.
  96. //-----------------------------------------------------------------------------
  97. CMyD3DApplication::CMyD3DApplication()
  98. {
  99.     m_strWindowTitle    = _T("VertexShader");
  100.     m_bUseDepthBuffer   = TRUE;
  101.  
  102.     m_pFont            = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  103.     m_pFontSmall       = new CD3DFont( _T("Arial"),  9, D3DFONT_BOLD );
  104.     m_pIB              = NULL;
  105.     m_pVB              = NULL;
  106.     m_dwSize           = 32;
  107.     m_dwNumIndices     = (m_dwSize - 1) * (m_dwSize - 1) * 6;
  108.     m_dwNumVertices    = m_dwSize * m_dwSize;
  109.     m_dwShader         = 0;
  110.  
  111.     ZeroMemory( m_bKey, sizeof(m_bKey) );
  112.     m_fSpeed           = 5.0f;
  113.     m_fAngularSpeed    = 1.0f;
  114.     m_bShowHelp        = FALSE;
  115.  
  116.     m_vVelocity        = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  117.     m_vAngularVelocity = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  118. }
  119.  
  120.  
  121.  
  122.  
  123. //-----------------------------------------------------------------------------
  124. // Name: OneTimeSceneInit()
  125. // Desc: Called during initial app startup, this function performs all the
  126. //       permanent initialization.
  127. //-----------------------------------------------------------------------------
  128. HRESULT CMyD3DApplication::OneTimeSceneInit()
  129. {
  130.     // Setup the view matrix
  131.     D3DXVECTOR3 vEye = D3DXVECTOR3( 2.0f, 3.0f, 3.0f );
  132.     D3DXVECTOR3 vAt  = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  133.     D3DXVECTOR3 vUp  = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  134.     D3DXMatrixLookAtRH( &m_matView, &vEye, &vAt, &vUp );
  135.  
  136.     // Set the position matrix
  137.     D3DXMatrixInverse( &m_matPosition, NULL, &m_matView );
  138.  
  139.     return S_OK;
  140. }
  141.  
  142.  
  143.  
  144.  
  145. //-----------------------------------------------------------------------------
  146. // Name: FrameMove()
  147. // Desc: Called once per frame, the call is the entry point for animating
  148. //       the scene.
  149. //-----------------------------------------------------------------------------
  150. HRESULT CMyD3DApplication::FrameMove()
  151. {
  152.     FLOAT fSecsPerFrame = m_fElapsedTime;
  153.  
  154.     // Process keyboard input
  155.     D3DXVECTOR3 vT( 0.0f, 0.0f, 0.0f );
  156.     D3DXVECTOR3 vR( 0.0f, 0.0f, 0.0f );
  157.  
  158.     if( m_bKey[VK_LEFT] || m_bKey[VK_NUMPAD1] )                 vT.x -= 1.0f; // Slide Left
  159.     if( m_bKey[VK_RIGHT] || m_bKey[VK_NUMPAD3] )                vT.x += 1.0f; // Slide Right
  160.     if( m_bKey[VK_DOWN] )                                       vT.y -= 1.0f; // Slide Down
  161.     if( m_bKey[VK_UP] )                                         vT.y += 1.0f; // Slide Up
  162.     if( m_bKey['W'] )                                           vT.z -= 2.0f; // Move Forward
  163.     if( m_bKey['S'] )                                           vT.z += 2.0f; // Move Backward
  164.     if( m_bKey['A'] || m_bKey[VK_NUMPAD8] )                     vR.x -= 1.0f; // Pitch Down
  165.     if( m_bKey['Z'] || m_bKey[VK_NUMPAD2] )                     vR.x += 1.0f; // Pitch Up
  166.     if( m_bKey['E'] || m_bKey[VK_NUMPAD6] )                     vR.y -= 1.0f; // Turn Right
  167.     if( m_bKey['Q'] || m_bKey[VK_NUMPAD4] )                     vR.y += 1.0f; // Turn Left
  168.     if( m_bKey[VK_NUMPAD9] )                                    vR.z -= 2.0f; // Roll CW
  169.     if( m_bKey[VK_NUMPAD7] )                                    vR.z += 2.0f; // Roll CCW
  170.  
  171.     m_vVelocity        = m_vVelocity * 0.9f + vT * 0.1f;
  172.     m_vAngularVelocity = m_vAngularVelocity * 0.9f + vR * 0.1f;
  173.  
  174.     // Update position and view matricies
  175.     D3DXMATRIX     matT, matR;
  176.     D3DXQUATERNION qR;
  177.  
  178.     vT = m_vVelocity * fSecsPerFrame * m_fSpeed;
  179.     vR = m_vAngularVelocity * fSecsPerFrame * m_fAngularSpeed;
  180.  
  181.     D3DXMatrixTranslation( &matT, vT.x, vT.y, vT.z);
  182.     D3DXMatrixMultiply( &m_matPosition, &matT, &m_matPosition );
  183.  
  184.     D3DXQuaternionRotationYawPitchRoll( &qR, vR.y, vR.x, vR.z );
  185.     D3DXMatrixRotationQuaternion( &matR, &qR );
  186.  
  187.     D3DXMatrixMultiply( &m_matPosition, &matR, &m_matPosition );
  188.     D3DXMatrixInverse( &m_matView, NULL, &m_matPosition );
  189.     m_pd3dDevice->SetTransform( D3DTS_VIEW, &m_matView );
  190.  
  191.     // Set up the vertex shader constants
  192.     {
  193.         D3DXMATRIX mat;
  194.         D3DXMatrixMultiply( &mat, &m_matView, &m_matProj );
  195.         D3DXMatrixTranspose( &mat, &mat );
  196.  
  197.         D3DXVECTOR4 vA( sinf(m_fTime)*15.0f, 0.0f, 0.5f, 1.0f );
  198.         D3DXVECTOR4 vD( D3DX_PI, 1.0f/(2.0f*D3DX_PI), 2.0f*D3DX_PI, 0.05f );
  199.  
  200.         // Taylor series coefficients for sin and cos
  201.         D3DXVECTOR4 vSin( 1.0f, -1.0f/6.0f, 1.0f/120.0f, -1.0f/5040.0f );
  202.         D3DXVECTOR4 vCos( 1.0f, -1.0f/2.0f, 1.0f/ 24.0f, -1.0f/ 720.0f );
  203.  
  204.         m_pd3dDevice->SetVertexShaderConstant(  0, &mat,  4 );
  205.         m_pd3dDevice->SetVertexShaderConstant(  4, &vA,   1 );
  206.         m_pd3dDevice->SetVertexShaderConstant(  7, &vD,   1 );
  207.         m_pd3dDevice->SetVertexShaderConstant( 10, &vSin, 1 );
  208.         m_pd3dDevice->SetVertexShaderConstant( 11, &vCos, 1 );
  209.     }
  210.  
  211.     return S_OK;
  212. }
  213.  
  214.  
  215.  
  216.  
  217. //-----------------------------------------------------------------------------
  218. // Name: Render()
  219. // Desc: Called once per frame, the call is the entry point for 3d
  220. //       rendering. This function sets up render states, clears the
  221. //       viewport, and renders the scene.
  222. //-----------------------------------------------------------------------------
  223. HRESULT CMyD3DApplication::Render()
  224. {
  225.     // Clear the backbuffer
  226.     m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
  227.                          0x000000ff, 1.0f, 0L );
  228.  
  229.     // Begin the scene
  230.     if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
  231.     {
  232.         m_pd3dDevice->SetVertexShader( m_dwShader );
  233.         m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(D3DXVECTOR2) );
  234.         m_pd3dDevice->SetIndices( m_pIB, 0 );
  235.         m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, m_dwNumVertices,
  236.                                             0, m_dwNumIndices/3 );
  237.  
  238.         // Output statistics
  239.         m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  240.         m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  241.  
  242.         if( m_bShowHelp )
  243.         {
  244.             m_pFontSmall->DrawText(  2, 40, D3DCOLOR_ARGB(255,255,255,255),
  245.                                     _T("Keyboard controls:") );
  246.             m_pFontSmall->DrawText( 20, 60, D3DCOLOR_ARGB(255,255,255,255),
  247.                                     _T("Move\nTurn\nPitch\nSlide\n")
  248.                                     _T("Help\nChange device\nExit") );
  249.             m_pFontSmall->DrawText( 210, 60, D3DCOLOR_ARGB(255,255,255,255),
  250.                                     _T("W,S\nE,Q\nA,Z\nArrow keys\n")
  251.                                     _T("F1\nF2\nEsc") );
  252.         }
  253.         else
  254.         {
  255.             m_pFontSmall->DrawText(  2, 40, D3DCOLOR_ARGB(255,255,255,255), 
  256.                                _T("Press F1 for help") );
  257.         }
  258.  
  259.  
  260.         // End the scene.
  261.         m_pd3dDevice->EndScene();
  262.     }
  263.  
  264.     return S_OK;
  265. }
  266.  
  267.  
  268.  
  269.  
  270. //-----------------------------------------------------------------------------
  271. // Name: InitDeviceObjects()
  272. // Desc: Initialize scene objects.
  273. //-----------------------------------------------------------------------------
  274. HRESULT CMyD3DApplication::InitDeviceObjects()
  275. {
  276.     m_pFont->InitDeviceObjects( m_pd3dDevice );
  277.     m_pFontSmall->InitDeviceObjects( m_pd3dDevice );
  278.     return S_OK;
  279. }
  280.  
  281.  
  282.  
  283.  
  284. //-----------------------------------------------------------------------------
  285. // Name: RestoreDeviceObjects()
  286. // Desc: Initialize scene objects.
  287. //-----------------------------------------------------------------------------
  288. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  289. {
  290.     HRESULT hr;
  291.  
  292.     m_pFont->RestoreDeviceObjects();
  293.     m_pFontSmall->RestoreDeviceObjects();
  294.  
  295.     // Setup render states
  296.     m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
  297.     m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
  298.  
  299.     // Create index buffer
  300.     {
  301.         WORD* pIndices;
  302.  
  303.         if( FAILED( hr = m_pd3dDevice->CreateIndexBuffer( m_dwNumIndices*sizeof(WORD),
  304.                                                           0, D3DFMT_INDEX16,
  305.                                                           D3DPOOL_DEFAULT, &m_pIB ) ) )
  306.             return hr;
  307.  
  308.         if( FAILED( hr = m_pIB->Lock( 0, m_dwNumIndices*sizeof(WORD), (BYTE**)&pIndices, 0 ) ) )
  309.             return hr;
  310.  
  311.         for( DWORD y=1; y<m_dwSize; y++ )
  312.         {
  313.             for( DWORD x=1; x<m_dwSize; x++ )
  314.             {
  315.                 *pIndices++ = (WORD)( (y-1)*m_dwSize + (x-1) );
  316.                 *pIndices++ = (WORD)( (y-0)*m_dwSize + (x-1) );
  317.                 *pIndices++ = (WORD)( (y-1)*m_dwSize + (x-0) );
  318.  
  319.                 *pIndices++ = (WORD)( (y-1)*m_dwSize + (x-0) );
  320.                 *pIndices++ = (WORD)( (y-0)*m_dwSize + (x-1) );
  321.                 *pIndices++ = (WORD)( (y-0)*m_dwSize + (x-0) );
  322.             }
  323.         }
  324.  
  325.         if( FAILED( hr = m_pIB->Unlock() ) )
  326.             return hr;
  327.     }
  328.  
  329.  
  330.     // Create vertex buffer
  331.     {
  332.         D3DXVECTOR2 *pVertices;
  333.  
  334.         if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( m_dwNumVertices*sizeof(D3DXVECTOR2),
  335.                                                            0, 0,
  336.                                                            D3DPOOL_DEFAULT, &m_pVB ) ) )
  337.             return hr;
  338.  
  339.         if( FAILED( hr = m_pVB->Lock( 0, m_dwNumVertices*sizeof(D3DXVECTOR2), (BYTE**)&pVertices, 0 ) ) )
  340.             return hr;
  341.  
  342.         for( DWORD y=0; y<m_dwSize; y++ )
  343.         {
  344.             for( DWORD x=0; x<m_dwSize; x++ )
  345.             {
  346.                 *pVertices++ = D3DXVECTOR2( ((float)x / (float)(m_dwSize-1) - 0.5f) * D3DX_PI,
  347.                                             ((float)y / (float)(m_dwSize-1) - 0.5f) * D3DX_PI );
  348.             }
  349.         }
  350.  
  351.         if( FAILED( hr = m_pVB->Unlock() ) )
  352.             return hr;
  353.     }
  354.  
  355.     // Create vertex shader
  356.     {
  357.         TCHAR        strVertexShaderPath[512];
  358.         LPD3DXBUFFER pCode;
  359.  
  360.         DWORD dwDecl[] =
  361.         {
  362.             D3DVSD_STREAM(0),
  363.             D3DVSD_REG(D3DVSDE_POSITION,  D3DVSDT_FLOAT2),
  364.             D3DVSD_END()
  365.         };
  366.  
  367.         // Find the vertex shader file
  368.         DXUtil_FindMediaFile( strVertexShaderPath, _T("Ripple.vsh") );
  369.  
  370.         // Assemble the vertex shader from the file
  371.         if( FAILED( hr = D3DXAssembleShaderFromFile( strVertexShaderPath, 
  372.                                                      0, NULL, &pCode, NULL ) ) )
  373.             return hr;
  374.  
  375.         // Create the vertex shader
  376.         hr = m_pd3dDevice->CreateVertexShader( dwDecl, (DWORD*)pCode->GetBufferPointer(),
  377.                                                &m_dwShader, 0 );
  378.         pCode->Release();
  379.         if( FAILED(hr) )
  380.             return hr;
  381.     }
  382.  
  383.     // Set up the projection matrix
  384.     FLOAT fAspectRatio = (FLOAT)m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height;
  385.     D3DXMatrixPerspectiveFovRH( &m_matProj, D3DXToRadian(60.0f), fAspectRatio, 0.1f, 100.0f );
  386.     m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &m_matProj );
  387.  
  388.     return S_OK;
  389. }
  390.  
  391.  
  392.  
  393.  
  394. //-----------------------------------------------------------------------------
  395. // Name: InvalidateDeviceObjects()
  396. // Desc:
  397. //-----------------------------------------------------------------------------
  398. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  399. {
  400.     m_pFont->InvalidateDeviceObjects();
  401.     m_pFontSmall->InvalidateDeviceObjects();
  402.     SAFE_RELEASE( m_pIB );
  403.     SAFE_RELEASE( m_pVB );
  404.     m_pd3dDevice->DeleteVertexShader( m_dwShader );
  405.  
  406.     return S_OK;
  407. }
  408.  
  409.  
  410.  
  411.  
  412. //-----------------------------------------------------------------------------
  413. // Name: DeleteDeviceObjects()
  414. // Desc: Called when the app is exiting, or the device is being changed,
  415. //       this function deletes any device dependent objects.
  416. //-----------------------------------------------------------------------------
  417. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  418. {
  419.     m_pFont->DeleteDeviceObjects();
  420.     m_pFontSmall->DeleteDeviceObjects();
  421.     return S_OK;
  422. }
  423.  
  424.  
  425.  
  426.  
  427. //-----------------------------------------------------------------------------
  428. // Name: FinalCleanup()
  429. // Desc: Called before the app exits, this function gives the app the chance
  430. //       to cleanup after itself.
  431. //-----------------------------------------------------------------------------
  432. HRESULT CMyD3DApplication::FinalCleanup()
  433. {
  434.     SAFE_DELETE( m_pFont );
  435.     SAFE_DELETE( m_pFontSmall );
  436.     return S_OK;
  437. }
  438.  
  439.  
  440.  
  441.  
  442. //-----------------------------------------------------------------------------
  443. // Name: ConfirmDevice()
  444. // Desc: Called during device intialization, this code checks the device
  445. //       for some minimum set of capabilities
  446. //-----------------------------------------------------------------------------
  447. HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,
  448.                                           D3DFORMAT Format )
  449. {
  450.     if( (dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING ) ||
  451.         (dwBehavior & D3DCREATE_MIXED_VERTEXPROCESSING ) )
  452.     {
  453.         if( pCaps->VertexShaderVersion < D3DVS_VERSION(1,0) )
  454.             return E_FAIL;
  455.     }
  456.  
  457.     return S_OK;
  458. }
  459.  
  460.  
  461.  
  462.  
  463. //-----------------------------------------------------------------------------
  464. // Name: MsgProc()
  465. // Desc: Message proc function to handle key and menu input
  466. //-----------------------------------------------------------------------------
  467. LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
  468.                                     LPARAM lParam )
  469. {
  470.     // Handle key presses
  471.     switch( uMsg )
  472.     {
  473.         case WM_KEYUP:
  474.             m_bKey[wParam] = 0;
  475.             break;
  476.  
  477.         case WM_KEYDOWN:
  478.             m_bKey[wParam] = 1;
  479.             break;
  480.  
  481.         case WM_COMMAND:
  482.             {
  483.                 switch( LOWORD(wParam) )
  484.                 {
  485.                 case IDM_TOGGLEHELP:
  486.                     m_bShowHelp = !m_bShowHelp;
  487.                     break;
  488.                 }
  489.             }
  490.     }
  491.  
  492.     // Pass remaining messages to default handler
  493.     return CD3DApplication::MsgProc( hWnd, uMsg, wParam, lParam );
  494. }
  495.  
  496.  
  497.  
  498.